using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
using System.Drawing.Design;


[assembly: WebResource("BrettResources.ServerControls.AutoComplete.js", "text/javascript")]
[assembly: WebResource("BrettResources.ServerControls.KeySortDropDownList_ClientEvents.js", "text/javascript")]

namespace BrettResources.ServerControls
{
    /// <summary>
    /// HTML Select list derived from the DropDownList control which enables auto-complete selection of items in the DropDownList as the user types in the control.
    /// </summary>
    [DefaultProperty("AutoCompleteEnabled")]
    [ToolboxData("<{0}:AutoCompleteDropDownList runat=server></{0}:AutoCompleteDropDownList>")]
    [Description("HTML Select list derived from the DropDownList control which enables auto-complete selection of items in the DropDownList as the user types in the control")]
    public class AutoCompleteDropDownList : DropDownList
    {
        #region Public Virtual Properties

        /// <summary>
        /// When set to true, javascript enabling auto-complete selection of items
        /// in the DropDownList as the user types in the control is added
        /// </summary>        
        [Category("Behavior")]
        [DefaultValue(true)]
        [Description("When set to true, javascript enabling auto-complete selection of items in the DropDownList as the user types in the control is added")]
        public virtual Boolean AutoCompleteEnabled
        {
            get
            {
                return ((ViewState["AutoCompleteEnabled"] == null) ? true : (Boolean)ViewState["AutoCompleteEnabled"]);
            }
            set
            {
                ViewState["AutoCompleteEnabled"] = value;
            }
        }

        /// <summary>
        /// defaults to false
        /// </summary>
        [Category("Behavior")]
        [DefaultValue(false)]
        public virtual Boolean CaseSensitiveKeySort
        {
            get
            {
                return ((ViewState["CaseSensitiveKeySort"] == null) ? false : (Boolean)ViewState["CaseSensitiveKeySort"]);
            }
            set
            {
                ViewState["CaseSensitiveKeySort"] = value;
            }
        }

        /// <summary>
        /// Allows referencing a specific file and function for the onkeypress javascript event
        /// </summary>        
        [Category("Behavior")]
        [DefaultValue(false)]        
        public virtual Boolean UseCustomSettings
        {
            get
            {
                return ((ViewState["UseCustomSettings"] == null) ? false : (Boolean)ViewState["UseCustomSettings"]);
            }
            set
            {
                ViewState["UseCustomSettings"] = value;
            }
        }

        /// <summary>
        /// Ex: "~/clientscript/AutoComplete.js"
        /// </summary>
        [Category("Behavior")]
        [Description("Ex: ~/clientscript/AutoComplete.js")]
        [Editor(typeof(System.Web.UI.Design.UrlEditor), typeof(UITypeEditor))]
        [UrlProperty("*.js")]
        public virtual string ExternalScriptSourceRelativeUrl
        {
            get
            {
                return ((string)ViewState["ExternalScriptSourceRelativeUrl"] == null) ? String.Empty : (string)ViewState["ExternalScriptSourceRelativeUrl"];
            }
            set
            {
                ViewState["ExternalScriptSourceRelativeUrl"] = value;
            }
        }
        #endregion

        #region Properties

        /// <summary>
        /// 
        /// </summary>
        [Category("Behavior")]
        [DefaultValue(null)]
        public virtual AutoCompleteCustomClientSettings CustomSettings
        {
            get { return ((AutoCompleteCustomClientSettings)ViewState["AutoCompleteCustomClientSettings"] == null) ? null : (AutoCompleteCustomClientSettings)ViewState["AutoCompleteCustomClientSettings"]; }
            set { ViewState["AutoCompleteCustomClientSettings"] = value; }
        }

        private Boolean BrowserSupportsJavascript
        {
            get
            {
                if (this.Context != null &&
                    this.Context.Request != null &&
                    this.Context.Request.Browser != null &&
                    this.Context.Request.Browser.EcmaScriptVersion != null)
                {
                    return (this.Context.Request.Browser.EcmaScriptVersion.Major >= 1);
                }
                else
                {
                    //for testing...
                    return true;
                }
            }
        }
        #endregion

        #region Overridden Events
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            base.AddAttributesToRender(writer);

            if (this.BrowserSupportsJavascript && this.AutoCompleteEnabled)
            {                
                writer.AddAttribute("onkeypress", this.GetOnKeyPressAttributeValue());
                writer.AddAttribute("onkeydown", "return KeySortDropDownList_onkeydown(event, this);");
                writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "return KeySortDropDownList_onclick(this," + this.SelectedIndex.ToString() + ");");
                writer.AddAttribute("onblur", "return KeySortDropDownList_onblur(this," + this.SelectedIndex.ToString() + ");");                
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (this.BrowserSupportsJavascript && this.AutoCompleteEnabled)
            {
                this.RegisterClientScriptInclude(
                    this.Page.ClientScript.GetWebResourceUrl(typeof(AutoCompleteDropDownList), "BrettResources.ServerControls.KeySortDropDownList_ClientEvents.js")
                    , "BrettResources.ServerControls.AutoComplete.ClientEvents");

                this.RegisterAutoCompleteJavaScript();
            }
        }
        #endregion

        #region Private Methods
        private void RegisterAutoCompleteJavaScript()
        {
            if (this.UseCustomSettings)
            {
                this.ValidateCustomSettings();

                if (string.IsNullOrEmpty(this.CustomSettings.ExternalScriptSourceRelativeUrl))
                {
                    this.RegisterClientScriptBlock(this.CustomSettings.ScriptBlock);
                }
                else
                {
                    this.RegisterClientScriptInclude(this.CustomSettings.ExternalScriptSourceRelativeUrl, "BrettResources.ServerControls.AutoComplete");
                }
            }
            else
            {
                if (string.IsNullOrEmpty(this.ExternalScriptSourceRelativeUrl))
                {
                    this.RegisterClientScriptInclude(
                        this.Page.ClientScript.GetWebResourceUrl(typeof(AutoCompleteDropDownList), "BrettResources.ServerControls.AutoComplete.js")
                        , "BrettResources.ServerControls.AutoComplete");
                }
                else
                {
                    this.RegisterClientScriptInclude(this.ExternalScriptSourceRelativeUrl , "BrettResources.ServerControls.AutoComplete");
                }
            }            
        }

        private void RegisterClientScriptBlock(String script)
        {
            if (!this.Page.ClientScript.IsClientScriptBlockRegistered("AutoCompleteDropDownListBlock"))
            {
                this.Page.ClientScript.RegisterClientScriptBlock(
                    this.GetType(),
                    "AutoCompleteDropDownListBlock",
                    script
                );
            }
        }

        private void RegisterClientScriptInclude(String relativeUrl, string key)
        {
            if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(key))
            {
                this.Page.ClientScript.RegisterClientScriptInclude(key, base.ResolveClientUrl(relativeUrl));
            }
        }

        private String GetOnKeyPressAttributeValue()
        {
            string AttributeValue = "";

            if (this.UseCustomSettings)
            {
                this.ValidateCustomSettings();
                AttributeValue = "return " + this.CustomSettings.FunctionName + this.CustomSettings.FunctionSignature + ";";
            }
            else
            {
                AttributeValue = "return KeySortDropDownList_onkeypress(this," + this.CaseSensitiveKeySort.ToString().ToLower() + ", event);";
            }

            return AttributeValue;
        }

        private void ValidateCustomSettings()
        {
            if (this.CustomSettings == null)
                throw new NullReferenceException("UseCustomSettings is set to true but no CustomSettings data was supplied.");
        }
        #endregion
    }
}
